14. Java.


14.1. Instalación de Java: JDK.

Para instalar Java, lo más sencillo es instalar los paquetes sun-java6-jdky todas sus dependencias, entre ellas: java-common, jun-java6-bin y sun-java6-jre. Requerirá 130 Mb de tu disco libre. Siempre podrás también descargarlo de la Web de Java http://java.sun.com/javase/downloads/index.jsp, en tal caso sigue las explicaciones de la guía Ubuntu, http://www.guia-ubuntu.org/index.php?title=Java. En la instalación tendrás que aceptar la licencia “Operating System Distributor License for Java DLJ”, ¡vaya nombrecito!

Observa que primero con java –version hemos comprobado que tenemos instalado el entorno de ejecución de Java (Runtime Environment), así como el compilador con javac –version.

Los siguientes pasos son:

1. Editar el archivo fuente seLibre.java.

2. Compilarlo: javac seLibre.java.

3. Ejecutar el lanzador de aplicaciones de Java: java seLibre.

Observa el listado del primer programa que debes realizar en Java:

public class seLibre {
  public static void main(String[] args) {
        System.out.println("Se Libre!");
        }
  }


14.2. Eclipse, un potente IDE a tu servicio.


14.2.1. Definición. Características.

Para los amantes de java, Eclipse es una buena opción, su página Web oficial es www.eclipse.org. Se trata de una aplicación de código abierto y multiplataforma elaborada por IBM. Un entorno de desarrollo profesional para aplicaciones desarrolladas bajo este lenguaje.


14.2.2. Instalación.

La instalación en Windows consiste en navegar a la sección de descargas de la página oficial http://www.eclipse.org/downloads/, elegir el IDE adecuado así como la plataforma, en este ejemplo elegimos Eclipse IDE for Java Developers. En otras palabras, entorno de desarrollo Eclipse para programadores de Java. Sigue los pasos del asistente que son bastante simples e indica donde desear crear el Espacio de Trabajo, es decir, el directorio de trabajo donde se almacenan los proyectos.

En Linux se instala con los paquetes eclipse y eclipse-nls (este segundo paquete incluye la extensión del idioma) y lo encontrarás en Aplicaciones, Programación, Eclipse. Al principio de la configuración te preguntará donde crear el Espacio de trabajo, por defecto será: /home/joe/workspace/.


14.2.3. Creación de proyectos con Eclipse.

Observa en la ilustración la pantalla de bienvenida, tienes acceso a tutoriales, ejemplos, etc.

Crea un nuevo proyecto: Archivo, Nuevo, Proyecto. Selecciona dentro de Java, Proyecto Java. Haz clic en Siguiente.

Ahora dale un nombre al proyecto, por ejemplo HolaMundoLibre.

Puedes elegir si deseas crear el proyecto en tu entorno o área de trabajo o crearlo a partir de uno ya existente, la versión del entorno de ejecución de java, etc.

Por lo general basta con dejar todas las opciones en sus valores por defecto. Haz clic en Finalizar.

Creamos una nueva clase de java con Archivo, Nueva, Clase.

Fíjate que hemos definido un paquete seLibre(los paquetes deben empezar en minúsculas), un nombre para la clase principal (SeLibre) que hereda de una clase padre (en Java existe un único árbol de herencia cuya raíz es la clase Object) y que nos cree el prototipo del método main.

Cuando hagas clic en Finalizar tendrás un esqueleto de proyecto con código ya escrito para aumentar tu productividad.

En Java todo son clases (Java es un lenguaje orientado a objetos puro) y se almacenan en archivos con la extensión .java, cuando éstos se compilan obtienes los ficheros.class.

Ahora procederemos a escribir el código necesario para ejecutar el programa más simple, el típico “Hola Mundo Libre”.

Fíjate en primer lugar en la parte izquierda de Eclipse. Tenemos el área de trabajo HolaMundoLibre, un paquete seLibre con una clase SeLibre en el fichero SeLibre.java.

El propio entorno de desarrollo simplifica la escritura de código mostrándote los métodos y clases a tu disposición, así como una explicación de los mismos. Escribe en el cuerpo del método main: System.out.println(“Hola Mundo Libre”) y guarda el proyecto: Archivo, Guardar o CTRL + S. Lanza el programa en Ejecutar, Ejecutar, Aplicación Java y observa el resultado en la consola en la parte inferior central de la figura.


14.3. Introducción a Java.


14.3.1. Un lenguaje orientado a objetos “puro”. Características.

Pero, ¿qué es Java? Java es un lenguaje de programación orientado a objetos puro, es decir, al contrario que con C++ donde la orientación a objetos se introdujo “ad hoc”, Java se diseño con el paradigma de la programación orientado a objetos desde el principio.

Las características de Java son las siguientes:

* Simple: nos olvidamos de la pesadilla de los punteros de C/C++ y sólo se permite la herencia simple.

* Seguro: al contrario que otras tecnologías Java se diseñó para ser seguro, por ejemplo, desde un Applet de una página Web nunca podremos conseguir acceso a los recursos de un cliente.

* Potente.

* Interpretado: con la idea de “Write once, Run everywhere” escribe el código una sola vez y ejecútalo bajo distintos sistemas operativos (Linux, Windows y Mac OS) y dispositivos (no sólo ordenadores, también móviles, pdas, etc.) que tengan la máquina virtual Java.

* Es una tecnología que puede ser utilizada para crear tanto una aplicación típica de escritorio como para crear servicios Web.


Cualquier programa en java (MiPrograma.java) debe compilarse. El resultado sería MiPrograma.class que contiene un código intermedio o bytecodes que puede ser ejecutado en una máquina virtual java (JVM). Como la máquina virtual está disponible en distintos sistemas operativos (Linux, Windows y Mac OS) la consecuencia es que nuestro programa podrá ejecutarse en todos ellos.


14.3.2. Mi primer programa en Java.

Observa un listado muy parecido al primero que realizamos en Java.

/**
  * La clase SeLibre nos provee de la capacidad de escribir
  * Se Libre! por la salida estándar (la consola)
  */
  public class SeLibre {
       public static void main(String[] args) {
        System.out.println("Se Libre!");
        }
  }

Las primeras líneas son comentarios. Estos no tienen ningún cometido respecto a la funcionalidad de la aplicación que estamos realizando. Su razón de ser estriba en ayudar al programador a entender y comprender mejor el código fuente. Ten en cuenta que este código es el “aeiou” de la programación y la función de estos comentarios es más bien una excusa para enseñarte su uso, pero cuando programas meses en el mismo o distintos proyectos, fácilmente olvidarás el sentido de lo que escribiste tiempo atrás.

Si en tu proyecto, hay varios programadores, la labor de comentar se convierte en esencial para aumentar la productividad y hacer posible la mantenibilidad del código a lo largo del tiempo y reusabilidad, es decir, que dicho código pueda reutilizarse en futuros proyectos. Además todo lo que se encierra entre “/**” y “*” es interpretado por la utilidad javadoc la cual nos permite generar páginas de ayuda HTML con nuestra documentación. Navega a http://java.sun.com/javase/6/docs/technotes/guides/javadoc/index.html para mayor información sobre esta magnífica herramienta.

En Java todos son clases y el nombre de la clase (en el ejemplo SeLibre) debe ser el mismo que el del nombre del fichero (SeLibre.java). Debes tener en consideración que no es lo mismo seLibre.java que SeLibre.java, es decir, debes distinguir entre mayúsculas y minúsculas. La línea del programa public class SeLibre define una nueva clase.


Una clase es la esencia de la programación orientada a objetos, el mundo se modela con objetos y clases. Por ejemplo, imagina la clase Coche. En la clase existen atributos o características, que definen las características del objeto, por ejemplo, matrícula, color, propietario, itv, etc. y métodos que implementan su funcionalidad serían: arrancar, parar, llenarGasolina, cambiarMarcha, etc.

En la siguiente línea se encuentra el método main. Este método es el principal, representa el punto de entrada y salida de nuestra aplicación.

En este método hemos invocado al método println que imprime por pantalla un mensaje. Esto se realiza llamando a un método println de la clase System.out, la salida estándar, la consola. Típicamente existe una entrada estándar (el teclado, la clase en Java que implementa su funcionalidad es System.in), la salida estándar (System.out) y el error estándar (System.err).

Para introducirte en Java, te aconsejamos los tutoriales de Java en inglés de la dirección http://java.sun.com/docs/books/tutorial/ y Java en castellano, http://www.programacion.net/java/. Para un usuario más experto puedes también querer consultar su especificación http://java.sun.com/docs/books/jls/.


14.3.3. Variables, tipos, operadores, estructuras de control y arrays.

Empecemos definiendo los distintos elementos de los que se compone cualquier lenguaje de programación.

Las variables se definen mediante un identificador y un tipo. Una variable puede ser concebida como una zona de memoria reservada con nombre que durante la ejecución de nuestro programa cambiará de valor. El identificador no puede ser una palabra reservada (ejemplos de palabras reservadas serían public, super, void, etc.) y puede estar formada por caracteres, números, el guión bajo, “_”, etc. sin embargo, no debes comenzar con un número sino con una letra en minúsculas. Ejemplo de definición de variables serían:

int matricula;
  String propietario=”Se Libre”

Los tipos son:

    * Enteros: int (será el que normalmente utilizarás), short (entero corto), byte (un byte, 8 bits), long (entero largo).

    * Boléanos: boolean (false, true).

    * Carácter: char, por ejemplo: ‘a’,’b’,’@’, ‘\r’ (retorno de carro), ‘\n’ (nueva línea), etc.

    * Reales: float, double.

  * Arrays (lista ordenada de elementos del mismo tipo): String dias_semana[]={“Lunes”,”Martes”, ….,”Domingo”};

Los operadores básicos serían:

    * Aritméticos: +,-,*,/, %(módulo),++(incremento), --(decremento),etc.

    * Lógicos: && (y), ||(o), ! (negación)

    * Relacionales: > (mayor que), < (menor que), >= (mayor o igual), <= (menor o igual), = = (igual, son dos “=” seguidos),!= (distinto).

    * De asignación: =, +=, -=, *=, /=, etc.

    * Sobre bits: & (y), | (o), ^ (xor), ~ (negación).

Existen dos conceptos importantes a la hora de tratar con los operadores, la asociatividad y la precedencia. Para poder utilizar los operadores debes conocer la precedencia, es decir el orden en el que serán evaluados. Sin entrar en un detalle exhaustivo que se sale del alcance de esta obra, de mayor a menor precedencia:

    * Operadores unarios: ++,--.

    * Multiplicación y división: *,/

    * Suma y resta: +,-

    * Operadores relacionales: >, <, >=, <=

    * Operadores lógicos: && (y), || (o)

Un ejemplo sería: x = y + 3 * z, sería equivalente a x = y + (3 * z).

La asociatividad se refiere al sentido en el que serán evaluados los operadores, normalmente será tal como se escribe, de izquierda a derecha, pero no siempre será así. Observa que la asignación tiene asociatividad a la derecha.

    * Supongamos el siguiente código: z=1; x=y =z+7=8;

    * Luego se evalúa y, y = 8.

    * Finalmente x = 8.

Para ser un buen programador te aconsejamos dos reglas. La primera es evitar expresiones muy largas y complejas, con muchos operandos y operadores. La segunda es separar los operandos de los operadores con espacios en blancos y utilizar paréntesis. La razón no es otra que hacer un código más limpio y legible. Así x=y+3*z debería ser sustituido por x = y + ( 3 * z );

Cualquier programa puede realizarse utilizando sólo tres estructuras básicas: secuencial, alternativa y repetitiva. La secuencial es la más normal, es un conjunto de sentencias que se ejecutan en orden. En el resto de ejemplos cuando leas sentencia, ten en consideración que puede ser una sola sentencia o un conjunto o bloque de sentencias, en este caso deben agruparse con llaves, por ejemplo if (condición) sentencia; sería también:

   if (condición) {
           Sentencia1;
           Sentencia2;
      …
           SentenciaN; }

Las estructuras de control alternativas ejecutan unas sentencias u otras en función de que se cumpla o no una determinada condición. Finalmente la estructura repetitiva es un grupo de instrucciones que se ejecutan repetidamente un número de veces o hasta que se cumpla (o deje de cumplirse) una determinada condición.

* Alternativa simple.

if (condición) sentencia;

Si se cumple la condición se ejecuta la sentencia.

* Alternativa doble.

if (condición) sentencia;

  else otraSentencia;

Si se cumple la condición se ejecuta la sentencia. En caso contrario se ejecuta otraSentencia.

* Alternativa múltiple.

if (condición1) sentencia1;

  else if (condición2) sentencia2;

  else if (condición3) sentencia3;

  […]

  else sentenciaN;

Si se cumple condición1 se ejecuta sentencia1. En caso contrario, si se cumple la condición2 se ejecuta la sentencia2. Así sucesivamente, si no se cumple ninguna de las condiciones se ejecuta sentenciaN.

* Switch

switch (expresión ) {

  case valor1:

    sentencia11;

    sentencia12;

    […]

    break;

case valor2:

    sentencia21;

    sentencia22;

    […]

    break;

[…]

default:

    sentencian1;

    sentencian2;

    […]

    break;

La sentencia switch evalúa expresión, si expresión es igual a valor1 ejecuta todas las sentencias asociadas (sentencia11, sentencia12, etc.) hasta que se encuentre un break.

La expresión puede ser una variable entera o de tipo carácter (char), en cada caso los valores serían por ejemplo: 1, 2, 3, etc. o ‘a’, ‘b’, ‘c’, etc. respectivamente. En el caso de que la variable no coincida con ninguno de los valores propuestos se ejecutan las sentencias asociada al bloque default.

* Repetitiva I: while

while (condición)

      sentencia;

Un error terrible es escribir,

while (condición);

sentencia;

Tendremos un bucle infinito porque si la condición es cierta ejecutará la sentencia vacía “;” que al no hacer nada y no alterar condición provocará un bucle sin fin.

Mientras se cumpla la condición se ejecuta la sentencia o bloque de sentencias. La condición se evalúa ANTES de comenzar el bucle de iteraciones, luego puede ocurrir que nunca se ejecuten las sentencias del bucle.

En este ejemplo sentencia1 y sentencia2 nunca se ejecutarán.

int variable = 7;

while (variable<0) {

    sentencia1;

    sentencia2;

}

Implícito está el hecho de que en el bucle debe modificarse la condición para no caer en un bucle infinito:

int variable = 7;

while (variable>0) {

    sentencia1;

    sentencia2;

    variable - -;

}

* Repetitiva II: do … while

do sentencia

    while (condición);

Mientras se cumpla la condición se ejecuta las sentencias del bucle. La condición se evalúa DESPUÉS de comenzar el bucle de iteraciones, por tanto al menos una vez se ejecuta las sentencias.

* Repetitiva III: for

for ( condición_inicio; condición_parada; incremento)

sentencia;

Ejemplo: Mostrará 1, 2, 3, ..., 10

for (int i=1; i<=10; i++)

{

    System.out.println(i);

}

Observa que la variable i es una variable local al bucle for, es decir, no podrá ser llamada desde fuera de dicho for.

La sentencia se ejecutará un número determinado de veces. Antes de empezar el bucle se evalúa la condición de inicio, la primera parte de la cláusula for. Luego se evalúa la condición de parada, si es cierta se ejecuta sentencia, para a continuación llamar a incremento antes de volver a evaluar la condición.

Si la primera vez que se evalúa la condición de parada no es cierta, no se entrará en el ciclo. Luego el for es un while camuflado, la condición se evalúa ANTES de comenzar el bucle.

Pongamos todo lo que hemos aprendido en práctica:

/**
  * La clase SeLibre nos provee de la capacidad de escribir
  * los días de la semana por consola
  */
  public class SeLibre {
   public static void main(String[] args) {
       String dias_semana[] = { “Lunes”, “ Martes”, “Miércoles”,...};
       System.out.println("Se Libre!");
       for (int i=0; i<dias_semana.length; i++)
       System.out.println(dias_semana[i]);
       }
  }

En este ejemplo cabe aclarar:

1. El miércoles lleva la tilde y se visualizará sin problemas, esto es así porque la codificación es UNICODE.

2. Observa que aunque ya lo sabíamos, por motivos pedagógicos para calcular la longitud o el número de elementos del array hemos utilizado la función length. Esto, sin embargo, no es una buena idea de cara a la eficiencia del programa, pues en cada vuelta del bucle se evaluará la condición y se invocará al método length.

3. La longitud del array es 7, sin embargo al igual que en C/C++ los elementos del array se enumeran del 0 al 6, luego el lunes sería dias_semana[0], el martes, dias_semana[1], etc.


14.3.4. Clases.

Java pertenece a los lenguajes que conforman la programación orientada a objetos. Este nuevo paradigma de programación supera en abstracción a la clásica programación estructurada permitiendo a los desarrolladores crear un código más sencillo y cercano al mundo que pretendemos implementar.

En la programación orientada a objetos el mundo se modela como un conjunto de clases. Una clase es una representación del mundo real que consta de atributos que especifican las características o propiedades de dicha clase y métodos que le dotan de funcionalidad. Así por ejemplo la clase Persona tendría unos atributos para describir sus propiedades, por ejemplo: edad, sexo, color_pelo, nombre, etc. y un conjunto de métodos, que implementarían las operaciones que podemos realizar sobre ella: cumplir_anyos, decirEdad, decirSexo, cambiarSexo (que hoy en día está tan de moda), etc. Si queremos trabajar con Persona crearemos objetos, estos son instancias u ocurrencias particulares de la clase Persona, por ejemplo la instancia Marta sería un objeto, una instancia particular de la clase Persona.

Vamos a seguir trabajando con Eclipse. Vamos a añadir una nueva clase a nuestro proyecto inicial, selecciona Archivo, Nueva, Clase y crearíamos la clase Complejo.

Observa que en este caso no creamos el método main, pues la aplicación estará formada de un determinado número de clases, pero sólo en una estará definida el método principal de entrada y salida a la aplicación.

Luego escribe el siguiente código:

Debes indicar en el cuadro de texto Paquete: en qué paquete quieres crear la clase.

Si lo quieres solo para usarlo con la aplicación inicial utiliza el paquete seLibre, sin embargo, si vas a crear una clase o conjunto de clases para ser utilizados por varias aplicaciones podrías crear otro paquete (por ejemplo, misClasesMates) y luego importarlo en cada uno de tus proyectos.

package seLibre;

Con esta línea indicamos que comienza la definición de la clase Complejo que va a implementar la funcionalidad de los números complejos. La cualidad de public permite a cualquiera crear instancias de la clase, si fuera protected sólo las clases derivadas podrían crear instancias.

public class Complejo {

En la primera parte definimos los atributos, por defecto estos tienen una visibilidad privada, es decir, podrán ser accesibles sólo desde los métodos de la clase. Un numero complejo sería real + imaginario i, luego precisamos dos atributos.

int real;
   int imaginario;

Este método que se llama de la misma forma que la clase es el constructor, es un método especial pues es el que se llama cuando se crea una instancia de la clase. Cuando en el cuerpo del método main hagamos b = new Complejo(2,4); será llamado el constructor que asignara a real el número 2 y a imaginario el número 4, nuestro objeto representará el número complejo 2 + 4i.

Complejo (int a, int b)
       {
          real = a;
          imaginario = b;
      }

En los dos próximos métodos implementamos la suma y el producto de complejos, se les pasa dos complejos como argumentos y devuelven otro complejo. Lo más significativo es que se tratan de métodos static, es decir, métodos de clase que no podrán ser invocados desde ninguna instancia de la clase, sino con el nombre de la clase, observa como se les llama desde main: c = Complejo.suma(a, b);

publicstatic Complejo suma(Complejo a, Complejo b)
   {
      Complejo resultado = new Complejo(a.real + b.real, a.imaginario + b.imaginario);
      return resultado;
    }
   public static Complejo producto(Complejo a, Complejo b){
      Complejo resultado = newComplejo(a.real * b.real -a.imaginario * b.imaginario, a.real * b.imaginario + a.imaginario * b.real);
      return resultado;
   }
   […]

Como punto final de esta primera aproximación a las clases de Java creamos un método de instancia, es decir un método que podrá ser llamado desde cualquier instancia de la clase (por ejemplo c), simplemente con c.toString();

La utilidad de este método es permitirnos visualizar una instancia de la clase de la forma en que tradicionalmente estamos acostumbrados a ver un número complejo: real + imaginario i

public String toString()
   {
      return real + " + " + imaginario + " i";
    }
}

Ahora desde la función main, podremos utilizar la nueva clase. Fíjate que al encontrarse en el mismo paquete no precisamos importarla:

public static void main(String[] args) {
      Complejo a = new Complejo(2,2);
      Complejo b = new Complejo(2,4);
      Complejo c = Complejo.suma(a, b);

Aunque para llamar a un método de instancia la forma tradicional es objeto.metodo_instancia(argumento1, …, argumentoN), para este caso bastaría con escribir directamente System.out.pringln(c), el compilador interpreta que este método es especial y sirve para mostrar objetos.


   System.out.print(c.toString());
   System.out.println(a.real); //Esta línea está MAL
   }


!ERROR! Observa que por defecto los atributos de la clase son privados, por tanto sólo son accesibles desde los métodos de la clase. Esta es una buena técnica de ocultación y suele ayudar en una programación más estructura y organizada.

Sin embargo, si quieres que fueran accesibles deberías cambiar la visibilidad en la definición de dichos atributos escribiendo:public int real;


Veamos otro código que podíamos haber realizado:

Podíamos haber definido varios constructores (oirás que Java permite la sobrecarga de métodos y en particular de los constructores), así si se llama con a = new Complejo(); se llamaría al primer constructor y se crearía el objeto complejo que representa a 1. Si llamáramos con a = new Complejo(3) se llamaría al segundo constructor. Fíjate que podemos tener varios constructores pero estos tienen que ser distintos en el número de argumentos y/o el tipo de estos.

Complejo ()
       {
         real = 1;
         imaginario = 0;
       }
      Complejo (int a)
      {
         real = a;
         imaginario = 0;
       }
}

Igual que tenemos métodos estáticos de clase podríamos tener atributos de clase, un ejemplo clásico sería un atributo que cuenta el número de instancias creadas de una clase. Se definiría también con la palabra reservada static, un ejemplo sería:

public class Complejo {
         int real;
         int imaginario;

Definimos un atributo de clase numeroComplejos y lo inicializamos a cero.

static int numeroComplejos = 0;
         Complejo (int a, int b)
         {
            real = a;
         imaginario = b;

En el constructor debemos incrementar esta variable para indicar que hemos creado una nueva instancia de la clase.

         numeroComplejos++;
       }

Finalmente crearás un método estático para mostrar el número de complejos que se han creado hasta el momento.

public static int numeroComplejos()
         {
           return numeroComplejos;
          }


14.3.5. La herencia en Java.

Las clases en el paradigma de la programación orientada a objetos se organizan de forma jerárquica. Veámoslo con un ejemplo, si estudiamos Biología y quisiéramos modelar el mundo, tendríamos la clase SeresVivos, de esta podrían heredar dos clases Animales y Vegetales. En este caso, SeresVivos es la superclase, la clase base o padre. Animales y Vegetales son las clases derivadas, extendidas o hijas. Ahora podrías considerar que Insectos, Mamíferos, etc. son clases derivadas de Animales, a su vez en Mamíferos podríamos tener la clase SerHumano, Perro, Gato, etc.

Observa que podemos crear una jerarquía de clases bastante compleja, sin embargo, debes valorar cómo de próximo al mundo real se encuentra nuestro modelo.


Además una vez que una clase hereda de otra, la clase descendiente o derivada reutiliza todos los miembros (atributos y métodos) de su superclase, es decir, sin la necesidad de reescribir ni depurar código la subclase hereda todos los miembros de su clase padre.

Por ejemplo si tienes el método mamar() en Mamíferos no será necesario implementarlo de nuevo en SerHumano, Perro o Gato, éstos ya lo heredan directamente.

Existen ocasiones donde una clase no implementa ninguna funcionalidad, sirve sólo para que los programadores sepan la interfaz que deben seguir las clases que la hereden o la implementen. Estas clases están definidas por la palabra reservada interface y están formados sólo por constantes y prototipos de métodos.

Podría darse el caso de que una interfaz sea heredada por otra interfaz, pero finalmente tendrá que ser implementada por al menos una clase donde se indique cual va a ser el código de los métodos definidos en la interfaz.

Si todo esto te ha resultado complejo, no te preocupes. Vamos a explicarlo paso a paso con un ejemplo sencillo. Lo primero que crearemos será una interfaz, recuerda que debemos utilizar la palabra reservada interface. FiguraGeometrica sólo nos sirve para indicar que cualquier figura geométrica deberá tener dos métodos: area(), que indica el área o extensión de dicha figura geométrica y perimetro() que debe devolvernos su perímetro o la longitud de su frontera (en un polígono sería la suma de sus lados).

package seLibre;
  public interface FiguraGeometrica {
       double area();
       double perimetro();
  }

El siguiente paso es crear dos clases que implementen dicha interfaz, es decir Cuadrado y Triángulo dirán finalmente cómo vamos a calcular el área y el perímetro. Dicho de otra manera FiguraGeometrica es una declaración de buenas intenciones, pero finalmente alguien deberá plasmar en código cómo se realizará. La forma de decir a Java que una clase implementa una interfaz es a través de la palabra reservada implements.

package seLibre;
  public class Cuadrado implements FiguraGeometrica{
    double lado;
    Cuadrado(double l)
   {
        lado = l;
   }
    public double area()
   {
        return lado * lado;
   }
    public double perimetro()
   {
        return 4 * lado;
   }
}

Observa que un cuadrado es un polígono con cuatro lados iguales, luego sólo precisamos indicar en el constructor la longitud del lado. El área es l 2 y el perímetro es, como en cualquier otro polígono, la longitud de sus lados, en este caso 4*l.

package seLibre;
   public class Triangulo implements FiguraGeometrica{
      double lado1;
      double lado2;
      double lado3;

En el constructor solicitamos la longitud de sus tres lados.

   Triangulo(double l1, double l2, double l3)
      {
         lado1 = l1;
         lado2 = l2;
         lado3 = l3;
    }
    public double area()
    {
       double semiperimetro = perimetro() / 2;
       return Math.sqrt(semiperimetro * (semiperimetro-lado1) * (semiperimetro-lado2) * (semiperimetro-lado3));
   }

Para calcular el área de un triángulo, hemos utilizado la fórmula de Heron, véase http://es.wikipedia.org/wiki/Triángulo para más información.


    public double perimetro()
    {
        return lado1 + lado2 + lado3;
    }

}

Sin embargo, en vez de trabajar siempre con triángulos, pudiera suceder que nos interese trabajar con Triángulos rectángulos. Un triángulo rectángulo es un tipo particular de triángulo, una subclase que se caracteriza por tener un ángulo recto, es decir de 90 grados. A los lados que configuran el ángulo recto se les denomina catetos y al tercero hipotenusa. Observa que en una subclase puedes volver a reescribir un método de la superclase, por ejemplo en este caso area() porque existe una implementación mas eficiente, en nuestro caso: . Donde base y altura son los dos catetos del triángulo rectángulo. Fíjate en el uso de la palabra reservada extends para definir que estamos heredando de Triángulo.

package seLibre;
  public class TrianguloRectangulo extends Triangulo implements FiguraGeometrica{
      double hipotenusa;
      double cateto1;
      double cateto2;
   

En el constructor primero llamamos al constructor de la clase padre, es decir de Triangulo, esto lo realizamos con el método super. Luego calculamos cual es el mayor de los tres lados, ese será la hipotenusa, los otros dos serán los catetos.

    public TrianguloRectangulo(double l1, double l2, double l3)
      {
          super(l1,l2,l3);
         hipotenusa = l1; cateto1 = l2; cateto2 = l3;
         if (l2 > l1) { hipotenusa = l2; cateto1 = l1; cateto2 = l3; }
         if (l3 >hipotenusa) { hipotenusa = l3; cateto1 = l1; cateto2 = l2; }
    }
    public double area()
   {
        return (cateto1 * cateto2 / 2);
    }

Observa que una subclase puede además definir nuevos métodos de instancia, en este caso este método muestra que el teorema de Pitágoras, es valido para nuestro triángulo.

public void pitagoras()
    {

Fíjate también en el uso de pow, la función potencia, esta función es un método estático, de clase, por tanto se llama con Math.pow.

      System.out.println("La hipotenusa al cuadrado: " + Math.pow(hipotenusa, 2));
      System.out.println("Es igual a la suma de los catetos: " + Math.pow(cateto1, 2) + " y " +  Math.pow(cateto2, 2));
    }
}

Finalmente veámos un código donde podamos llamar a las clases que hemos definido. Considera que nunca podrás crear una instancia de una interfaz, pero si de cualquier clase y de sus derivadas.

public class SeLibre {
      public static void main(String[] args) {
            CuadradomyCuadrado = new Cuadrado(5);
            System.out.println(myCuadrado.area());
            System.out.println(myCuadrado.perimetro());
            Triangulo myTriangulo = new Triangulo(25,20,15);
            System.out.print(myTriangulo.perimetro());

            TrianguloRectangulomyTriangulo2 = new
   TrianguloRectangulo(25,20,15);

            System.out.print(myTriangulo2.area());
            myTriangulo2.pitagoras();
   }
}


14.3.6. Creando tu primer applet: “Hola Mundo Libre”.

Una explicación detallada de cómo realizar applets se sale fuera del alcance de esta obra, si quieres profundizar visita las direcciones: http://java.sun.com/docs/books/tutorial/deployment/applet/index.html y http://www.javapassion.com/handsonlabs/OLDuiswing/uiswing/learn/example1.html. Considera este epígrafe un pequeño resumen de los contenidos que en las URL antes mencionadas puedes encontrar.

Un applet no es una aplicación. La vida de un applet sigue los siguientes eventos que llaman a unos determinados métodos:

* Inicialización, vía el método init.

* Inicio de la ejecución, se llama al método start.

* Parada del applet, el método es stop.

* Fin de la vida del applet y limpieza final, se llama al método destroy.

Un applet debe heredar de Applet o JApplet, en nuestro caso va a heredar de JApplet para utilizar toda la potencia de Swing. Al ser un programa Swing debes tener en cuenta que existen varios tipos de threads.


Un thread o hilo de ejecución es un trozo de código en ejecución. En Swing disponemos de tres tipos de threads: hilos iniciales (los que ejecutan el código inicial), el hilo manejador u organizador de eventos (es donde se ejecuta el código que maneja los eventos) y los hilos de segundo plano (son las tareas que consumen abundantes ciclos de CPU).

En nuestro caso como vivimos en un applet, los hilos iniciales crean un objeto Applet e invocan a los métodos init y start. Así pues el hilo inicial crea un objeto Runnable que inicializa la GUI y se pone a la espera de ser llamado por el manejador de eventos como respuesta a algún evento, por ejemplo, que hagamos clic con el ratón sobre un botón que vamos a crear.

public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            creaMuestraGUI();
        }
    });
    }
}

Lo siguiente que vamos a hacer es crear y mostrar nuestra GUI, es decir, nuestra interfaz de usuario.

private static void creaMuestraGUI() {

En primer lugar creamos el contenedor principal. Este contenedor provee una simple ventana principal con el soporte para manejar eventos y dibujarse. Además esta ventana tiene ya toda la funcionalidad y la interfaz que se le supone, es decir, los botones de minimizar, maximizar y cerrar, su título y el borde.

    JFrame frame = new JFrame("Hola Mundo");

Para que el botón cerrar funcione: precisamos invocar al método setDefaultCloseOperation (asignar la operación de cierre por defecto) de JFrame, el argumento es una constante de JFrame, en particular EXIT_ON_CLOSE, que indica que la aplicación finalice la ejecución.

   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Creamos una instancia de nuestro Applet.

   MiApplet miPanel = new MiApplet();

JFrame es un contenedor que tiene un panel de contenido. Este contiene los componentes visibles de dicho contenedor, para agregar un componente debes añadirlo con el método setContetPane, y como argumento el componente que quieres agregar, en nuestro caso nuestro propio JApplet.

   frame.setContentPane(miPanel);

Finalmente veamos qué realizamos en el constructor.

public MiApplet()
            {

Vamos a crear un botón con un icono, la clase ImageIcon será la que nos provea esta funcionalidad.

   ImageIcon myIcon;

java.net.URL es una clase que representa una URL, esto es, un recurso de Internet, léase una dirección Web, una dirección a un fichero en tu ordenador, una consulta a una base de datos o a un motor de búsqueda.

Como paso previo crea en tu directorio de trabajo una carpeta imágenes y dentro de esta introduces el icono que quieres mostrar en el botón. Para obtener la dirección a nuestra imagen debes llamar al método getResource indicándole como argumento la ruta o el path a dicho recurso, en nuestro caso “imágenes/linux.jpg”.

   java.net.URL miURL = MiApplet.class.getResource("imagenes/linux.jpg");

Si dicha dirección es null nos salimos del constructor, hemos fracasado. En otro caso, si todo ha marchado bien, creamos el icono con una llamada a su constructor y como argumento la Url de nuestro icono.

   if (miURL!=null){
                            myIcon = new ImageIcon(miURL);

Luego creamos nuestro botón llamando al constructor JButton, con dos argumentos: el texto inicial y el icono.


                            miboton = new JButton("Haz clic",myIcon);
                      }
                     else return;
   

Finalmente podemos definir las propiedades de nuestro botón, así por ejemplo, podemos ajustar el tamaño de nuestro botón.

                     miboton.setSize(20, 20);

Ahora viene lo más importante vamos a dotar de funcionalidad a nuestro botón. Debemos indicar en primer lugar con setActionCommand el nombre de la orden, en nuestro caso: “clic”.

   miboton.setActionCommand("clic");

Luego hemos de decirle quien va a ser el que escuche y maneje nuestros eventos, en este caso el mismo Applet, de ahí que lo indiquemos con la palabra reservada this. En tal caso hemos de implementar la función actionPerformed que será la que responda a los eventos.

   miboton.addActionListener(this);

Añadimos el botón al contenedor. Recuerda que lo hemos creado, configurado e indicado cual es su manejador de eventos pero no lo habíamos agregado al contenedor.

   add(miboton);
      }

Ahora tenemos que implementar la función actionPerformed que será invocada cuando el usuario realice una acción sobre el botón, en nuestro caso haga clic sobre él.

public void actionPerformed(ActionEvent e){

Lo primero que haremos es comprobar que el evento está asociado con la orden que queremos manejar. El método equals de la clase String compara la cadena “clic” con la cadena que devuelve e.getActionCommand() (la orden asociada al evento e).


    if ("clic".equals(e.getActionCommand()))
       {

Si son iguales, significa que estamos manejando la orden “clic” de miboton. Como respuesta a dicho evento, vamos a hacer que el botón cambie el texto que muestra.

miboton.setText("Me has pulsado");
       }
   }


Finalmente observa el código fuente completo. Sólo hemos de añadir que debes importar las distintas clases import javax.swing.JApplet o paquetes import java.awt.event.*. Además fíjate que MiApplet hereda de JApplet e implementa la interfaz ActionListener.

import javax.swing.JApplet;
   import java.awt.Graphics;
   import javax.swing.JFrame;
   import javax.swing.JButton;
   import java.awt.event.*;
   import javax.swing.ImageIcon;

   public class MiApplet extends JApplet implements ActionListener{

       private static final long serialVersionUID = 1L;
      protected JButton miboton;

   public MiApplet()
   {
       ImageIcon myIcon;
       java.net.URL miURL = MiApplet.class.getResource("imagenes/linux.jpg");
       if (miURL!=null)
       {
        myIcon = new ImageIcon(miURL);
        miboton = new JButton("Haz clic",myIcon);
       }
    else return;
   
       miboton.setSize(20, 20);
       miboton.setActionCommand("clic");
       miboton.addActionListener(this);
       add(miboton);
   }
   public void actionPerformed(ActionEvent e){
       if ("clic".equals(e.getActionCommand()))
       {
           miboton.setText("Me has pulsado");
       }
   }
    private static void creaMuestraGUI() {
       JFrame frame = new JFrame("Hola Mundo");
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       MiApplet miPanel = new MiApplet();
       frame.setContentPane(miPanel);
       frame.pack();
       frame.setVisible(true);
   
   }
   public static void main(String[] args) {
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               creaMuestraGUI();
           }
       });
       }
   }

Para ejecutar el applet, haz clic sobre el fichero MiApplet.java con el botón derecho del ratón y selecciona la opción Ejecutar como, Applet java.

En la figura inferior podrás ver el detalle de tu Applet.

Quizás estés un poco defraudado porque hemos realizado mucho trabajo y parece que tampoco hemos obtenido gran cosa.

No te preocupes, la base está construida, ahora dotar a tu Applet de mayor funcionalidad es mucho más sencillo.

En el constructor hemos añadido sólo un botón, pero tienes a tu disposición toda la potencia de Swing, así podrás añadir:

* JLabel: etiquetas con texto e imágenes.

* JProgressBar: barras de progreso.

* JSeparator: un separador.

* JToolTip: la típica ayuda o leyenda que ayuda al usuario a saber moverse por la interfaz.

* JTable: una tabla.

* JTextArea: un área de texto.

* JMenu: un menú.

* Otros controles como: JCheckBox, JComboBox, JList, etc.


Veamos un ejemplo más complicado. Para evitarnos tener que escribir una cadena de import demasiado larga, importa los siguientes paquetes:

import javax.swing.*;
   import java.awt.*;
   import java.awt.event.*;

import javax.swing.*;
   import java.awt.*;
   import java.awt.event.*;

   public class MiApplet extends JApplet implements ActionListener{

    private static final long serialVersionUID = 1L;
   protected JButton miboton;

En linuxPath, windowsPath y macPath guardaremos la ruta donde se encuentran las imágenes.


   static String linuxPath="imagenes/linux.jpg";
   static String windowsPath="imagenes/windows.jpeg";
   static String macPath="imagenes/mac.jpeg";

En linuxString, windowsString y macString guardaremos el texto que vamos a mostrar al usuario en función de su elección.

static String linuxString="Linux";
   static String windowsString="Windows";
   static String macString="Mac";
   JLabel myJLabel;
   java.net.URL imgURL;


   public MiApplet()
   {

Vamos a crear varios JRadioButton, estos son botones circulares, que nos muestran si están seleccionados o no. Crearemos tres: myRadioButtonLinux, myRadioButtonWindows y myRadioButtonMax.

En el constructor indicamos el texto que el usuario verá asociado a dicho botón.

        JRadioButton myRadioButtonLinux = new JRadioButton(linuxString);

Ahora indicamos la orden que asociaremos a este botón.

       myRadioButtonLinux.setActionCommand(linuxPath);

Tendremos seleccionado la primera vez myRadioButtonLinux.

       myRadioButtonLinux.setSelected(true);

Ahora debemos indicar quien va a responder a los eventos generados desde este botón, en este caso el propio Applet.

       myRadioButtonLinux.addActionListener(this);


Llamando al método setToolTipText mostramos un texto de ayuda al usuario cuando con el ratón se aproxime al botón.

Así cuando el ratón se posiciona sobre uno de los botones radiales, en el ejemplo el del Windows, se muestra “Selecciona Windows”.

myRadioButtonLinux.setToolTipText("Selecciona Linux");

Los otros dos botones se crean de la misma forma. Solo ten en cuenta que inicialmente solo uno estará seleccionado.

    JRadioButton myRadioButtonWindows = new JRadioButton(windowsString);        myRadioButtonWindows.setActionCommand(windowsPath);
        myRadioButtonWindows.setSelected(false);
        myRadioButtonWindows.addActionListener(this);
        myRadioButtonWindows.setToolTipText("Selecciona Windows");
       
        JRadioButton myRadioButtonMac = new JRadioButton(macString);

        myRadioButtonMac.setActionCommand(macPath);
        myRadioButtonMac.setSelected(true);
        myRadioButtonMac.addActionListener(this);
        myRadioButtonMac.setToolTipText("Selecciona Mac OS");

Ahora creamos un objeto ButtonGroup que contenga a todos los botones. Este objeto implementa la funcionalidad de que al hacer clic sobre uno y seleccionarlo, automáticamente deselecciona los demás.

    ButtonGroup myButtonGroup = new ButtonGroup();
        myButtonGroup.add(myRadioButtonLinux);
        myButtonGroup.add(myRadioButtonWindows);
        myButtonGroup.add(myRadioButtonMac);

Lo siguiente es crear una imagen con la opción que el usuario haya seleccionado. La primera vez hemos configurado por defecto el botón de Linux, luego debe mostrarse la imagen de Linux. Esta se indica con la cadena de texto, o mejor con la instancia de la clase String linuxPath.

imgURL = MiApplet.class.getResource(linuxPath);
           if (imgURL== null) return;
           else
               myJLabel = new JLabel(new ImageIcon(imgURL));

No podemos incrustar los botones directamente sobre nuestro applet. Debemos incrustarlo en un contenedor JPanel. Este implementa un contenedor ligero conveniente para muchos usos. Además en el constructor especificamos cual será el gestor de Layout (puedes traducirlo como gestor de posicionamiento o distribución si prefieres) en este caso GridLayout (otra opción sería un BorderLayout con cinco regiones: Norte, Sur, Este, Oeste y Central), que divide el espacio de trabajo en una cuadrícula rectangular, en nuestro caso con 0 filas y 1 columna, es decir que contenga una sola celda.

    JPanel myPanel = new JPanel(new GridLayout(0,1));
              myPanel.add(myRadioButtonLinux);
              myPanel.add(myRadioButtonWindows);
              myPanel.add(myRadioButtonMac);

Un efecto similar lo hubiéramos obtenido con este código:

        JPanel myPanel = new JPanel(new BorderLayout());
        myPanel.add(myRadioButtonLinux,BorderLayout.NORTH);
        myPanel.add(myRadioButtonWindows, BorderLayout.CENTER);
        myPanel.add(myRadioButtonMac, BorderLayout.SOUTH);



Oeste

Norte


Este

Central

Sur

En este caso agregamos tanto myPanel como myJLabel en la zona Oeste y Central respectivamente del Applet.

add(myPanel, BorderLayout.WEST);
        add(myJLabel, BorderLayout.CENTER);
   }

Observa que myPanel vive en Oeste luego su posicionamiento se refiere a esta zona (en negrita en la figura).


Norte

Oeste

Central

Este

Sur

Norte


Este

Central

Sur


Fíjate en el resultado final, también puedes observar un cuadro de diálogo.

Ahora iremos a por ello, de momento, observa la distribución de los distintos botones y la etiqueta en el Applet.

Observa la figura de la derecha, ¿qué crees que habrá ocurrido? Este es el código que cambia el posicionamiento de los elementos del interfaz:

        JPanel myPanel = new JPanel(new BorderLayout());
    myPanel.add(myRadioButtonLinux,BorderLayout.NORTH);
    myPanel.add(myRadioButtonWindows, BorderLayout.CENTER);


myPanel.add(myRadioButtonMac, BorderLayout.EAST);


      Finalmente, implementamos el método que responderá a los eventos que se dispararán cuando el usuario seleccione un botón radial. 

public void actionPerformed(ActionEvent e){

Primero capturamos la dirección URL de la imagen que corresponde al botón de radio seleccionado.

   imgURL = MiApplet.class.getResource(e.getActionCommand());
          if (imgURL== null) return;
          else

Con dicha URL cambiamos el icono de nuestra etiqueta para que muestre el adecuado al botón seleccionado.

       myJLabel.setIcon(new ImageIcon(imgURL));

Con una simple línea mostramos un cuadro de diálogo, la típica ventana de información.

 JOptionPane.showMessageDialog(this, "Pásate a Linux");

   }

El resto de código es casi idéntico a lo que ya se ha explicado.


private static void creaMuestraGUI() {
    JFrame.setDefaultLookAndFeelDecorated(true);
    JFrame frame;
    frame = new JFrame("Hola Mundo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    MiApplet miPanel = new MiApplet();
    frame.setContentPane(miPanel);
    frame.pack();
    frame.setVisible(true);   
}
public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            creaMuestraGUI();
        }
    });
    }
}